#include "GlobalData.h"

OpenGLWindow gWindow;
Input gInput;
GraphicsSystem gGraphics;
WorldMap gWorldMap;

float gMouseX;
float gMouseY;

bool gPause = false;
bool gTabDown = false;
int gCurrentFile = 1;

bool gChangeAttribute = false;
std::string gAttributeName = "Sleepiness";

AgentModel* gTargetAgent = NULL;
bool gTrackingOn = false;

ObjectModel::ObjectModel( std::string textureName, Vector2f pos, Vector2f scale ) {
  graphicID = AddGraphicObject( textureName, (int)pos[0], (int)pos[1], (int)scale[0], (int)scale[1] );
  position = pos;
  Stevescale = scale;
}

ObjectModel::~ObjectModel() {
  DeleteGraphicObject( graphicID );
}

void ObjectModel::MoveObject( Vector2f target ) { 
  position = target; 
  gGraphics.LocateObject( graphicID ).translation = target;
}

Vector2f ObjectModel::GetPosition() {
  return position;
}

Vector2f ObjectModel::GetStevescale() {
  return Stevescale;
}


AgentModel::AgentModel( std::string filename, Vector2f pos, Vector2f scale, float newSpeed ) {
  graphicID = AddGraphicObject( filename, (int)pos[0], (int)pos[1], (int)scale[0], (int)scale[1] );
  position = pos;
  speed = newSpeed;
  pathingToObject = false;
}
AgentModel::~AgentModel() {
  DeleteGraphicObject( graphicID );
}

void AgentModel::MoveObject( Vector2f target ) { 
  position = target; 
  gGraphics.LocateObject( graphicID ).translation = target;
}

Vector2f AgentModel::GetPosition() {
  return position;
}

bool AgentModel::UpdateMovement() {
  if( path.size() ) {
    Vector2f target = path[path.size()-1];
    Vector2f vec = (target - position);
    if( vec.Magnitude() <= speed ) {
      MoveObject( target );
      path.pop_back();
    }
    else {
      vec.Normalize();
      MoveObject( position + vec*speed );
    }
    return true;
  }
  return false;
}

void AgentModel::AttachPath( const std::vector<Vector2f>& newPath ) {
  path = newPath;
}

void AgentModel::RemovePath() {
  path.clear();
}


/////////////////////////////////////////////
//
//   World Map code begins here
//
/////////////////////////////////////////////
WorldMap::WorldMap()
{
	for (int y = -7;y <= 7;++y)
	{
		for (int x = -7;x <= 7;++x)
		{
			WorldGrid[y + 7][x + 7].Coords.x = (float)x;
			WorldGrid[y + 7][x + 7].Coords.y = (float)y;

			WorldGrid[y + 7][x + 7].Agent = NULL;
			WorldGrid[y + 7][x + 7].Object = NULL;

			WorldGrid[y + 7][x + 7].IsWall = false;
		}
	}
}

WorldMap::~WorldMap()
{
	AgentList.clear();
	ObjectList.clear();
}

void WorldMap::RegisterAgent(AgentModel &Agent)
{
	AgentList.push_back(&Agent);
	return;
}

bool WorldMap::RegisterObject(ObjectModel &Object, bool IsWall)
{
	int XCoord = (int)Object.GetPosition()[0] + 7;
	int YCoord = (int)Object.GetPosition()[1] + 7;

  if( WorldGrid[ YCoord ][ XCoord ].Object )
    return false; // Location is already filled

	ObjectList.push_back(&Object);
	WorldGrid[ YCoord ][ XCoord ].Object = &Object;

	if (IsWall == true)
	{
		for (int dy = -((int)Object.GetStevescale()[1] - 1);dy <=  ((int)Object.GetStevescale()[1] - 1);++dy)
		{
			for (int dx = -((int)Object.GetStevescale()[0] - 1);dx <=  ((int)Object.GetStevescale()[0] - 1);++dx)
			{
				WorldGrid[ (YCoord + dy) ][ (XCoord + dx) ].IsWall = true;
			}
		}
	}

	return true;
}

bool WorldMap::IsWall( int posX, int posY ) {
  posX += 7;
  posY += 7;

  if( !WorldGrid[posY][posX].IsWall )
    return true;
  return false;
}

void WorldMap::ClearMap() {
	for (int y = -7;y <= 7;++y)
	{
		for (int x = -7;x <= 7;++x)
		{
			WorldGrid[y + 7][x + 7].Agent = NULL;
			WorldGrid[y + 7][x + 7].Object = NULL;
		}
	}

  WorldMap::AgtIter iterAgt = AgentList.begin();
  WorldMap::AgtIter endAgt = AgentList.end();
  while( iterAgt != endAgt ) {
    delete (*iterAgt);
    ++iterAgt;
  }
  AgentList.clear();

  WorldMap::ObjIter iterObj = ObjectList.begin();
  WorldMap::ObjIter endObj = ObjectList.end();
  while( iterObj != endObj ) {
    delete (*iterObj);
    ++iterObj;
  }
  ObjectList.clear();
}

void WorldMap::ClearObjects() {
	for (int y = -7;y <= 7;++y)
	{
		for (int x = -7;x <= 7;++x)
		{
			WorldGrid[y + 7][x + 7].Object = NULL;
		}
	}

  WorldMap::ObjIter iterObj = ObjectList.begin();
  WorldMap::ObjIter endObj = ObjectList.end();
  while( iterObj != endObj ) {
    if( (*iterObj)->brain.GetName() != "DEFAULT_Wall" ) {
      delete (*iterObj);
    }
    ++iterObj;
  }
  ObjectList.clear();
}

void WorldMap::ClearAgents() {
	for (int y = -7;y <= 7;++y)
	{
		for (int x = -7;x <= 7;++x)
		{
			WorldGrid[y + 7][x + 7].Agent = NULL;
		}
	}

  WorldMap::AgtIter iterAgt = AgentList.begin();
  WorldMap::AgtIter endAgt = AgentList.end();
  while( iterAgt != endAgt ) {
    delete (*iterAgt);
    ++iterAgt;
  }
  AgentList.clear();
}